<template>
  <div id="docsearch">
    <AppButton button-class="DocSearch DocSearch-Button" aria-label="Search">
      <svg width="20" height="20" class="d-icon m-auto" viewBox="0 0 20 20">
        <path
          d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z"
          stroke="currentColor"
          fill="none"
          fill-rule="evenodd"
          stroke-linecap="round"
          stroke-linejoin="round"
        ></path>
      </svg>
    </AppButton>
  </div>
</template>

<script>
function isSpecialClick(event) {
  return event.button === 1 || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey
}

export default {
  props: {
    options: {
      type: Object,
      required: true
    },
    settings: {
      type: Object,
      required: true
    }
  },
  watch: {
    '$i18n.locale'(newValue) {
      this.update(this.options, newValue)
    },
    options(newValue) {
      this.update(newValue, this.$i18n.locale)
    }
  },
  mounted() {
    this.initialize(this.options, this.$i18n.locale)
  },
  methods: {
    stripTrailingSlash(url) {
      return url.replace(/\/$|\/(?=\?)|\/(?=#)/g, '')
    },
    getRelativePath(absoluteUrl) {
      const { pathname, hash } = new URL(absoluteUrl)
      const url = pathname.replace(this.settings.url, '/') + hash
      return this.stripTrailingSlash(url)
    },
    initialize(userOptions, code) {
      const lang = this.$i18n.locales.find(locale => locale.code === code)

      Promise.all([
        import(/* webpackChunkName: "docsearch" */ '@docsearch/js'),
        import(/* webpackChunkName: "docsearch" */ '@docsearch/css')
      ]).then(([docsearch]) => {
        docsearch = docsearch.default

        docsearch(
          Object.assign({}, userOptions, {
            container: '#docsearch',
            searchParameters: Object.assign(
              {},
              lang && {
                facetFilters: [`${userOptions.langAttribute || 'language'}:${lang.iso}`].concat(
                  userOptions.facetFilters || []
                )
              }
            ),
            navigator: {
              navigate: ({ suggestionUrl }) => {
                const { pathname: hitPathname } = new URL(window.location.origin + suggestionUrl)

                // Vue Router doesn't handle same-page navigation so we use
                // the native browser location API for anchor navigation.
                if (this.$router.history.current.path === hitPathname) {
                  window.location.assign(window.location.origin + suggestionUrl)
                } else {
                  this.$router.push(suggestionUrl)
                }
              }
            },
            transformItems: items => {
              return items.map(item => {
                return Object.assign({}, item, {
                  url: this.getRelativePath(item.url)
                })
              })
            },
            hitComponent: ({ hit, children }) => {
              return {
                type: 'a',
                ref: undefined,
                constructor: undefined,
                key: undefined,
                props: {
                  href: hit.url,
                  onClick: event => {
                    if (isSpecialClick(event)) {
                      return
                    }

                    // We rely on the native link scrolling when user is
                    // already on the right anchor because Vue Router doesn't
                    // support duplicated history entries.
                    if (this.$router.history.current.fullPath === hit.url) {
                      return
                    }

                    const { pathname: hitPathname } = new URL(window.location.origin + hit.url)

                    // If the hits goes to another page, we prevent the native link behavior
                    // to leverage the Vue Router loading feature.
                    if (this.$router.history.current.path !== hitPathname) {
                      event.preventDefault()
                    }

                    this.$router.push(hit.url)
                  },
                  children
                }
              }
            }
          })
        )
      })
    },
    update(options, lang) {
      this.initialize(options, lang)
    }
  }
}
</script>

<style lang="postcss">
.DocSearch {
  --docsearch-primary-color: #00dc82;
  --docsearch-highlight-color: var(--docsearch-primary-color);
  --docsearch-text-color: rgb(113, 113, 122);
  --docsearch-modal-background: theme('colors.gray.100');
  --docsearch-searchbox-shadow: 0 0 0 2px var(--docsearch-primary-color);
  --docsearch-searchbox-background: var(--color-transparent);
  --docsearch-searchbox-focus-background: var(--color-transparent);
  --docsearch-hit-color: var(--color-gray-700);
  --docsearch-hit-shadow: none;
  --docsearch-logo-color: var(--docsearch-text-color);
  --docsearch-muted-color: var(--color-gray-500);
  --docsearch-container-background: rgb(244 244 245 / 55%);
}

.dark {
  & .DocSearch {
    --docsearch-text-color: rgb(146, 173, 173);
    --docsearch-modal-background: theme('colors.secondary-darker');
    --docsearch-modal-shadow: inset 1px 1px 0 0 #052f14, 0 3px 8px 0 #0b160d;
    --docsearch-hit-color: var(--color-gray-300);
    --docsearch-hit-background: theme('colors.secondary-darkest');
    --docsearch-footer-background: theme('colors.secondary-darkest');
    --docsearch-footer-shadow: inset 0 1px 0 0 rgba(73, 76, 106, 0.5), 0 -4px 8px 0 rgba(0, 0, 0, 0.2);
    --docsearch-container-background: rgb(0 30 38 / 64%);
  }
}

.DocSearch-Container {
  @apply blur-8;
}
.DocSearch-Modal {
  @apply lg:rounded-xl !important;
}
.DocSearch-SearchBar {
  @apply pb-1 !important;
}
.DocSearch-Button {
  @apply rounded-sm w-12 h-12 m-auto bg-transparent hover:shadow-none focus:outline-none !important;
}
.DocSearch-Button > svg {
  @apply mx-auto !important;
}
.DocSearch-Button-Key {
  @apply hidden !important;
}
.DocSearch-Button-Placeholder {
  @apply hidden !important;
}
.DocSearch-NoResults > .DocSearch-Screen-Icon > svg {
  @apply mx-auto !important;
}
.DocSearch-Commands-Key {
  @apply inline-flex items-center justify-center w-auto h-auto p-1 bg-none rounded shadow-none border light:border-gray-500 !important;
}
</style>
